package us.kg.kotoriforest.aop.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 用于记录日志的切面类
 *
 * @author Kotori rotroutine@163.com
 * @since 2025/1/6
 */
@Aspect // 说明该类是切面类
@Component // 将对象放入IOC容器中管理
public class LogAspect {
    @Before("execution(public int us.kg.kotoriforest.aop.proxy.impl.CalculatorImpl.*(..))")
    public void before(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println("Logger-->前置通知，方法名：" + methodName + "，参数：" + args);
    }

    @After("pointCut()")
    public void after(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println("Logger-->后置通知，方法名：" + methodName + "，参数：" + args);
    }

    @AfterReturning(value = "execution(public int us.kg.kotoriforest.aop.proxy.impl.CalculatorImpl.*(..))", returning = "returnValue")
    public void afterReturning(JoinPoint joinPoint, Object returnValue) {
        String methodName = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println("Logger-->返回通知，方法名：" + methodName + "，参数：" + args + ",返回值: " + returnValue);
    }

    @AfterThrowing(value = "execution(public void us.kg.kotoriforest.aop.proxy.impl.CalculatorImpl.exception())", throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println("Logger-->异常通知，方法名：" + methodName + "，参数：" + args + ",返回值: " + ex.getMessage());
    }

    @Around("execution(public int us.kg.kotoriforest.aop.proxy.impl.CalculatorImpl.*(..))")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object returnValue = null;
        try {
            System.out.println("调用方法之前");
            returnValue = joinPoint.proceed();
            System.out.println("调用方法之后");
        } catch (Throwable e) {
            System.out.println("发生异常");
            throw new RuntimeException(e);
        } finally {
            System.out.println("finally");
        }

        System.out.println("返回");
        return returnValue;
    }

    // 重用切入点表达式
    @Pointcut("execution(* us.kg.kotoriforest.aop.proxy.impl.CalculatorImpl.*(..))")
    public void pointCut() {
    }
}
